#include "PhysicalDevice.h"

mini_engine::PhysicalDevice *mini_engine::PhysicalDevice::m_physicalDevice = nullptr;
VkPhysicalDevice mini_engine::PhysicalDevice::physicalDevice;

void mini_engine::PhysicalDevice::pickUpPhyiscalDevice()
{
    uint32_t deviceCount = 0;
    vkEnumeratePhysicalDevices(Instance::instance, &deviceCount, nullptr);

    if (deviceCount == 0)
    {
        throw std::runtime_error("failed to find GPUs with Vulkan support!");
    }

    std::vector<VkPhysicalDevice> devices(deviceCount);
    vkEnumeratePhysicalDevices(Instance::instance, &deviceCount, devices.data());

    for (const auto &device : devices)
    {
        if (isDeviceSuitable(device))
        {
            physicalDevice = device;
            break;
        }
    }

    if (physicalDevice == VK_NULL_HANDLE)
    {
        throw std::runtime_error("failed to find a suitable GPU!");
    }
}

/**
 * 设备适配性检查
 */
bool mini_engine::PhysicalDevice::isDeviceSuitable(VkPhysicalDevice device)
{
    cout << "Check if the device is compatible." << endl;
    QueueFamilyIndices indices = QueueFamilies::getQueueFamilies()->findQueueFamilyIndices(device);
    return indices.isComplete();
}

mini_engine::PhysicalDevice::PhysicalDevice()
{
}

mini_engine::PhysicalDevice *mini_engine::PhysicalDevice::getPhysicalDevice()
{
    if (m_physicalDevice == nullptr)
    {
        m_physicalDevice = new PhysicalDevice();
        static PhysicalDeviceDestruction physicalDeviceDestruction;
    }
    return m_physicalDevice;
}

mini_engine::PhysicalDevice::~PhysicalDevice()
{
}

mini_engine::PhysicalDevice::PhysicalDeviceDestruction::~PhysicalDeviceDestruction()
{
    if (m_physicalDevice != nullptr)
    {
        delete m_physicalDevice;
        m_physicalDevice = nullptr;
    }
}
